﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Mechanical;
using YArchitech.LIB;
using YArchitech.Public;
using YArchitech.Revit;

namespace YArchitech.HVAC
{
	public class ConnAlignment
	{
		public Document Doc { get; set; }

		public string ErrorString { get; set; }

		public ConnAlignment(Document doc)
		{
			this.Doc = doc;
		}

		public virtual bool connectAlignment(List<Duct> ducts, List<XYZ> points)
		{
			return false;
		}

		public virtual List<Duct> GetNewdDucts(List<Duct> ducts, List<XYZ> points)
		{
			return new List<Duct>();
		}

		public virtual List<Alignments> GetAlignment(List<Duct> ducts)
		{
			return new List<Alignments>();
		}

		public virtual bool MeetFittingCondition(List<Duct> ducts, List<XYZ> points)
		{
			return false;
		}

		public virtual List<Alignments> GetAlignmentBeforeSperate(List<Duct> ducts)
		{
			return new List<Alignments>();
		}

		public virtual List<string> GetNineFamilyNames()
		{
			return new List<string>();
		}

		public virtual bool GetFamilyName(List<Duct> ducts, NineAlignments na, ref string familyName)
		{
			return false;
		}

		protected List<Alignments> GetAlignmentByYShapeTee(List<Duct> ducts)
		{
			YJKPiping<Duct> hypiping = new YJKPiping<Duct>(ducts[0]);
			YJKPiping<Duct> hypiping2 = new YJKPiping<Duct>(ducts[1]);
			Connector closeConnector = hypiping.GetCloseConnector(hypiping2.StartConnector.Origin, false);
			List<Alignments> verticalAlignmentsByTwoDucts = new DetermineTwoDuctsAlignment(closeConnector.CoordinateSystem.BasisZ, ducts[0], ducts[1]).GetVerticalAlignmentsByTwoDucts();
			if (verticalAlignmentsByTwoDucts.Count <= 0)
			{
				this.ErrorString = "第一根管和第二根管没有符合的对齐方式";
				return null;
			}
			DetermineTwoDuctsAlignment determineTwoDuctsAlignment = new DetermineTwoDuctsAlignment(-closeConnector.CoordinateSystem.BasisX, ducts[1], ducts[2]);
			List<Alignments> verticalAlignmentsByTwoDucts2 = determineTwoDuctsAlignment.GetVerticalAlignmentsByTwoDucts();
			if (verticalAlignmentsByTwoDucts2.Count <= 0)
			{
				this.ErrorString = "第二根管和第三根管没有符合的对齐方式";
				return null;
			}
			List<Alignments> list = verticalAlignmentsByTwoDucts.Intersect(verticalAlignmentsByTwoDucts2).ToList<Alignments>();
			if (list.Count <= 0)
			{
				this.ErrorString = "三根管没有共同的对齐方式";
				return null;
			}
			if (list.Count > 1)
			{
				list.Clear();
				list.Add(Alignments.VerticalMiddle);
			}
			List<Alignments> horizontalAlignmentsByTwoDucts = determineTwoDuctsAlignment.GetHorizontalAlignmentsByTwoDucts();
			if (horizontalAlignmentsByTwoDucts.Count <= 0)
			{
				this.ErrorString = "第二根管和第三根管没有符合的对齐方式";
				return null;
			}
			if (horizontalAlignmentsByTwoDucts.Count > 1)
			{
				horizontalAlignmentsByTwoDucts.Clear();
				horizontalAlignmentsByTwoDucts.Add(Alignments.HorizontalMiddle);
			}
			return list.Union(horizontalAlignmentsByTwoDucts).ToList<Alignments>();
		}

		protected List<Alignments> GetAlignmentByRoundAngleTee(List<Duct> ducts)
		{
			YJKPiping<Duct> hypiping = new YJKPiping<Duct>(ducts[0]);
			YJKPiping<Duct> hypiping2 = new YJKPiping<Duct>(ducts[1]);
			Connector closeConnector = hypiping.GetCloseConnector(hypiping2.StartConnector.Origin, false);
			DetermineTwoDuctsAlignment determineTwoDuctsAlignment = new DetermineTwoDuctsAlignment(closeConnector.CoordinateSystem.BasisZ, ducts[0], ducts[1]);
			List<Alignments> verticalAlignmentsByTwoDucts = determineTwoDuctsAlignment.GetVerticalAlignmentsByTwoDucts();
			if (verticalAlignmentsByTwoDucts.Count <= 0)
			{
				this.ErrorString = "第一根管和第二根管没有符合的对齐方式";
				return null;
			}
			List<Alignments> verticalAlignmentsByTwoDucts2 = new DetermineTwoDuctsAlignment(closeConnector.CoordinateSystem.BasisZ, ducts[0], ducts[2]).GetVerticalAlignmentsByTwoDucts();
			if (verticalAlignmentsByTwoDucts2.Count <= 0)
			{
				this.ErrorString = "第一根管和第三根管没有符合的对齐方式";
				return null;
			}
			List<Alignments> list = verticalAlignmentsByTwoDucts.Intersect(verticalAlignmentsByTwoDucts2).ToList<Alignments>();
			if (list.Count <= 0)
			{
				this.ErrorString = "三根管没有共同的对齐方式";
				return null;
			}
			if (list.Count > 1)
			{
				list.Clear();
				list.Add(Alignments.VerticalMiddle);
			}
			List<Alignments> horizontalAlignmentsByTwoDucts = determineTwoDuctsAlignment.GetHorizontalAlignmentsByTwoDucts();
			if (horizontalAlignmentsByTwoDucts != null && horizontalAlignmentsByTwoDucts.Count > 1)
			{
				horizontalAlignmentsByTwoDucts.Clear();
				horizontalAlignmentsByTwoDucts.Add(Alignments.HorizontalMiddle);
			}
			return list.Union(horizontalAlignmentsByTwoDucts).ToList<Alignments>();
		}

		protected List<Alignments> GetAlignmentTeeBeforeSperate(List<Duct> ducts)
		{
			YJKPiping<Duct> hypiping = new YJKPiping<Duct>(ducts[0]);
			YJKPiping<Duct> hypiping2 = new YJKPiping<Duct>(ducts[2]);
			List<Alignments> verticalAlignmentsByTwoDucts = new DetermineTwoDuctsAlignment(hypiping.GetCloseConnector(hypiping2.StartConnector.Origin, false).CoordinateSystem.BasisZ, ducts[0], ducts[2]).GetVerticalAlignmentsByTwoDucts();
			if (verticalAlignmentsByTwoDucts.Count <= 0)
			{
				this.ErrorString = "第一根管和第三根管没有符合的对齐方式";
				return null;
			}
			if (verticalAlignmentsByTwoDucts.Count > 1)
			{
				verticalAlignmentsByTwoDucts.Clear();
				verticalAlignmentsByTwoDucts.Add(Alignments.VerticalMiddle);
			}
			List<Alignments> second = new List<Alignments>
			{
				Alignments.HorizontalMiddle
			};
			return verticalAlignmentsByTwoDucts.Union(second).ToList<Alignments>();
		}

		protected List<Duct> GetOrderedDucts(List<Duct> listDuct, XYZ pickPoint)
		{
			List<Duct> list = new List<Duct>();
			YJKPiping<Duct> hypiping = new YJKPiping<Duct>(listDuct[0]);
			YJKPiping<Duct> hypiping2 = new YJKPiping<Duct>(listDuct[1]);
			double num = hypiping.GetProject(pickPoint).DistanceTo(pickPoint);
			double num2 = hypiping2.GetProject(pickPoint).DistanceTo(pickPoint);
			if (num > num2)
			{
				list.Add(listDuct[1]);
				list.Add(listDuct[0]);
			}
			else
			{
				list.Add(listDuct[0]);
				list.Add(listDuct[1]);
			}
			return list;
		}

		protected List<Duct> GetDuctsBySperateDuct(Duct speratedDuct, Duct otherDuct, XYZ xyz)
		{
			YJKPiping<Duct> hypiping = new YJKPiping<Duct>(speratedDuct);
			YJKPiping<Duct> hypiping2 = new YJKPiping<Duct>(otherDuct);
			XYZ dlineP = YJKRevitTools.GetDLineP(hypiping2.StartConnector.Origin, hypiping2.EndConnector.Origin, hypiping.StartConnector.Origin, hypiping.EndConnector.Origin);
			if (dlineP == null)
			{
				this.ErrorString = "第一根管和第三根管没有交点";
				return null;
			}
			YJKRotateFamilyInstance hyrotateFamilyInstance = new YJKRotateFamilyInstance();
			List<Duct> list = new List<Duct>();
			list = hypiping.Separate(dlineP);
			hyrotateFamilyInstance.MovePiping(list[0]);
			hyrotateFamilyInstance.MovePiping(list[1]);
			return this.GetOrderedDucts(list, xyz);
		}

		protected NineAlignments GetOneAlignInNineAlignments(List<Alignments> list)
		{
			if (list.Count != 2)
			{
				return NineAlignments.None;
			}
			Alignments alignments = list[0];
			Alignments alignments2 = list[1];
			if (alignments == Alignments.Top)
			{
				if (alignments2 == Alignments.Left)
				{
					return NineAlignments.TopLeft;
				}
				if (alignments2 == Alignments.Right)
				{
					return NineAlignments.TopRight;
				}
				if (alignments2 == Alignments.HorizontalMiddle)
				{
					return NineAlignments.TopMiddle;
				}
			}
			else if (alignments == Alignments.Bottom)
			{
				if (alignments2 == Alignments.Left)
				{
					return NineAlignments.BottomLeft;
				}
				if (alignments2 == Alignments.Right)
				{
					return NineAlignments.BottomRight;
				}
				if (alignments2 == Alignments.HorizontalMiddle)
				{
					return NineAlignments.BottomMiddle;
				}
			}
			else if (alignments == Alignments.VerticalMiddle)
			{
				if (alignments2 == Alignments.Left)
				{
					return NineAlignments.MiddleLeft;
				}
				if (alignments2 == Alignments.Right)
				{
					return NineAlignments.MiddleRight;
				}
				if (alignments2 == Alignments.HorizontalMiddle)
				{
					return NineAlignments.MiddleMiddle;
				}
			}
			return NineAlignments.None;
		}

		protected FamilySymbol GetFamilySymbol(string fsName, Document doc)
		{
			FamilySymbol familySymbol = null;
			if (string.IsNullOrEmpty(fsName))
			{
				this.ErrorString = "族名不能为空！";
				return familySymbol;
			}
			familySymbol = YJKRevitTools.GetFamilySymbol(fsName, doc);
			if (familySymbol == null)
			{
				string text = Path.Combine(Product.FamilyLocation, RevitVersion.Version, "Fitting", fsName + ".rfa");
				if (!File.Exists(text))
				{
					this.ErrorString = "族不存在或者加载地址不正确！";
					return familySymbol;
				}
				SubTransaction subTransaction = new SubTransaction(doc);
				subTransaction.Start();
				Family family = null;
				doc.LoadFamily(text, out family);
				if (family == null)
				{
					subTransaction.RollBack();
					return null;
				}
				familySymbol = YJKRevitTools.GetFamilySymbol(fsName, doc);
				subTransaction.Commit();
			}
			return familySymbol;
		}

		protected FamilyInstance GetFamilyInstance(Document doc, IList<Duct> ducts, string familyName, bool isMirror)
		{
			FamilySymbol familySymbol = this.GetFamilySymbol(familyName, doc);
			if (familySymbol == null)
			{
				this.ErrorString = "加载族失败！";
				return null;
			}
			YJKPiping<Duct> hypiping = new YJKPiping<Duct>(ducts[0]);
			YJKPiping<Duct> hypiping2 = new YJKPiping<Duct>(ducts[2]);
			Connector closeConnector = hypiping.GetCloseConnector(hypiping2.StartConnector.Origin, false);
			SubTransaction subTransaction = new SubTransaction(doc);
			subTransaction.Start();
			UnifiedModified.ActivateFamilySymbol(familySymbol);
			FamilyInstance familyInstance = doc.Create.NewFamilyInstance(closeConnector.Origin, familySymbol, 0);
			doc.Regenerate();
			if (isMirror)
			{
				familyInstance = this.GetMirrorTee(familyInstance);
			}
			subTransaction.Commit();
			return familyInstance;
		}

		protected FamilyInstance GetMirrorTee(FamilyInstance teeFi)
		{
			Document document = teeFi.Document;
			HYSystemElementFilter hysystemElementFilter = new HYSystemElementFilter(document);
			YJKRotateFamilyInstance hyrotateFamilyInstance = new YJKRotateFamilyInstance();
			IList<Element> allDuctFitting = hysystemElementFilter.GetAllDuctFitting();
			Connector teeMainConnector = new ConnectHelper().GetTeeMainConnector(teeFi);
			hyrotateFamilyInstance.MirrorFamilyInstance(teeFi, teeMainConnector.CoordinateSystem.BasisZ, teeMainConnector.CoordinateSystem.BasisY, teeMainConnector.Origin);
			document.Regenerate();
			IList<Element> allDuctFitting2 = hysystemElementFilter.GetAllDuctFitting();
			FamilyInstance result = hysystemElementFilter.GetNewDuctFitting(allDuctFitting, allDuctFitting2) as FamilyInstance;
			document.DeleteElement(teeFi);
			return result;
		}

		protected void RotateElementToAlignAllDucts(FamilyInstance teeFi, Connector connA, Connector connB, Connector connC, Document doc)
		{
			ConnectHelper connectHelper = new ConnectHelper();
			Connector teeMainConnector = connectHelper.GetTeeMainConnector(teeFi);
			this.RotateElementByBaseVactor(connA, teeFi, teeMainConnector);
			Connector connector = connectHelper.GetTeeOutConnector(teeFi, connC.CoordinateSystem.BasisZ);
			if (connector == null)
			{
				connector = this.RotateFamilyInstance(teeFi, connC, connectHelper, teeMainConnector);
			}
			if (connector != null)
			{
				YJKLine hyline = new YJKLine(Line.CreateUnbound(connC.Origin, connC.CoordinateSystem.BasisZ));
				if (!hyline.IsPointOnLine(connector.Origin))
				{
					XYZ xyz = hyline.GetProject(connector.Origin) - connector.Origin;
					ElementTransformUtils.MoveElement(doc, teeFi.Id, xyz);
				}
			}
		}

		protected void RotateElementByBaseVactor(Connector connDuct, Element ele, Connector connTee)
		{
			XYZ xyz = -connDuct.CoordinateSystem.BasisZ;
			XYZ basisZ = connTee.CoordinateSystem.BasisZ;
			XYZ xyz2 = basisZ.CrossProduct(xyz).Normalize();
			if (xyz2.IsAlmostEqualTo(new XYZ(0.0, 0.0, 0.0)))
			{
				xyz2 = new XYZ(0.0, 0.0, 1.0);
			}
			double angleOnPlaneTo = YJKRevitTools.GetAngleOnPlaneTo(basisZ, xyz, xyz2);
			XYZ point = ((LocationPoint)ele.Location).Point;
			Line line = Line.CreateBound(point, point.Add(xyz2));
			ElementTransformUtils.RotateElement(ele.Document, ele.Id, line, angleOnPlaneTo);
			new YJKRotateFamilyInstance().MoveFamilyInstance(ele as FamilyInstance, new XYZ(0.0, 1.0, 0.0));
			connTee = new ConnectHelper().GetTeeOutConnector(ele as FamilyInstance, -xyz);
			YJKLine hyline = new YJKLine(Line.CreateUnbound(connDuct.Origin, -xyz));
			if (!hyline.IsPointOnLine(connTee.Origin))
			{
				XYZ xyz3 = hyline.GetProject(connTee.Origin) - connTee.Origin;
				ElementTransformUtils.MoveElement(ele.Document, ele.Id, xyz3);
			}
		}

		protected Connector RotateFamilyInstance(FamilyInstance teeFi, Connector connC, ConnectHelper cm, Connector teeMainConn)
		{
			XYZ basisZ = teeMainConn.CoordinateSystem.BasisZ;
			Connector teeSideConnector = cm.GetTeeSideConnector(teeFi, basisZ);
			XYZ basisZ2 = teeSideConnector.CoordinateSystem.BasisZ;
			XYZ vector = connC.CoordinateSystem.BasisZ * -1.0;
			double twoVectorAngle = YJKRevitTools.GetTwoVectorAngle(basisZ2, vector, basisZ);
			new YJKRotateFamilyInstance().RotateElem(teeFi, teeMainConn.Origin, basisZ, twoVectorAngle * 180.0 / Math.PI);
			return teeSideConnector;
		}

		protected void ModifySizeAndConnect(List<Connector> listConn, FamilyInstance fi)
		{
			int num = 0;
			foreach (Connector connector in listConn)
			{
				Connector connectorByTheSameVector = this.GetConnectorByTheSameVector(fi, -connector.CoordinateSystem.BasisZ);
				connectorByTheSameVector.Width = connector.Width;
				connectorByTheSameVector.Height = connector.Height;
				if (num == 0)
				{
					XYZ xyz = new YJKLine(Line.CreateUnbound(connector.Origin, connector.CoordinateSystem.BasisZ)).GetProject(connectorByTheSameVector.Origin) - connectorByTheSameVector.Origin;
					ElementTransformUtils.MoveElement(fi.Document, fi.Id, xyz);
					num++;
				}
				connector.ConnectTo(connectorByTheSameVector);
			}
		}

		protected Connector GetConnectorByTheSameVector(FamilyInstance fi, XYZ vector)
		{
			Connector result = null;
			if (fi != null)
			{
				ConnectorSetIterator connectorSetIterator = fi.MEPModel.ConnectorManager.Connectors.ForwardIterator();
				while (connectorSetIterator.MoveNext())
				{
					object obj = connectorSetIterator.Current;
					Connector connector = obj as Connector;
					if (connector != null && connector.CoordinateSystem.BasisZ.IsAlmostEqualTo(vector, 0.001))
					{
						result = connector;
					}
				}
			}
			return result;
		}
	}
}
